package site.xuqing.socketbus.core;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;

import site.xuqing.socketbus.core.handler.ClientReceiveHandler;
import site.xuqing.socketbus.core.handler.ClientSendHandler;
import site.xuqing.socketbus.listener.OnMsgReceive;
import site.xuqing.socketbus.uitls.NoBeanUtil;

/**
 * @author xuqing
 * @Description SocketClient类，用于管理连接
 * @createTime 2022年01月21日 09:59:07
 */
public class SocketClient extends Thread {
    private ClientReceiveHandler clientReceiveHandler;
    private ClientSendHandler clientSendHandler;
    private final int port;
    private final String route;
    private int localPort;
    private final OnMsgReceive mOnMsgReceive;
    private volatile boolean open = true;
    
    public SocketClient(int port, String route, OnMsgReceive onMsgReceive) {
        this.port = port;
        this.route = route;
        this.mOnMsgReceive = onMsgReceive;
    }
    
    public void close() {
        this.open = false;
    }
    
    private void client() {
        try {
            Socket socket = new Socket();
            //设置读取超时时间为2秒
            //socket.setSoTimeout(5000);
            // 是否需要在长时无数据响应时发送确认数据（类似心跳包），时间大约为2小时
            socket.setKeepAlive(true);
            // 设置接收发送缓冲器大小
            socket.setReceiveBufferSize(64 * 1024 * 1024);
            socket.setSendBufferSize(64 * 1024 * 1024);
            // 绑定到本地20001端口
            //socket.bind(new InetSocketAddress(Inet4Address.getLocalHost(), LOCAL_PORT));
            // 链接到本地20000端口，超时时间3秒，超过则抛出超时异常
            socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), port), 0);
            
            System.out.println("已发起服务器连接，并进入后续流程～");
            System.out.println("客户端信息：" + socket.getLocalAddress() + " P:" + socket.getLocalPort());
            System.out.println("服务器信息：" + socket.getInetAddress() + " P:" + socket.getPort());
            
            localPort = socket.getLocalPort();
            
            try {
                clientReceiveHandler = new ClientReceiveHandler(socket,mOnMsgReceive);
                clientReceiveHandler.start();
                clientSendHandler = new ClientSendHandler(socket);
                //给服务器发送一条绑定消息
                clientSendHandler.sendBind(NoBeanUtil.getBindEvent(socket.getLocalPort(),route));
                //下面这一句竟然能解决cup占用过高的情况，不是亲眼所见是万万不能相信的
                while (open) {
                    Thread.sleep(10000);
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("异常关闭");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public int getLocalPort() {
        return localPort;
    }
    
    public ClientSendHandler getClientSendHandler() {
        return clientSendHandler;
    }
    
    public ClientReceiveHandler getClientReceiveHandler() {
        return clientReceiveHandler;
    }
    
    @Override
    public void run() {
        client();
    }
}
